package com.onpositive.notes.parser;


import java.util.ArrayList;
import java.util.Map;

import com.onpositive.units.ParsedScalar;

public class ScalarParser extends AbstractParser {
	
	private static final long serialVersionUID = 5413089770042292552L;


	public ScalarParser() {
		super();
	}

	public static final String OCCUPIED_POSITIONS = "occupiedPositions";


	private Integer readNumber(String str ) {
		
		String value = str.trim().toLowerCase() ;
		
		if( value.startsWith("zero") )		 return  0 ;
		if( value.startsWith("one") )		 return  1 ;
		if( value.startsWith("two") )		 return  2 ;
		if( value.startsWith("three") )		 return  3 ;
		if( value.startsWith("four") )		 return  4 ;
		if( value.startsWith("five") )		 return  5 ;
		if( value.startsWith("six") )		 return  6 ;
		if( value.startsWith("seven") )		 return  7 ;
		if( value.startsWith("eight") )		 return  8 ;
		if( value.startsWith("nine") )		 return  9 ;
		if( value.startsWith("ten") )		 return 10 ;
		if( value.startsWith("eleven") )	 return 11 ;
		if( value.startsWith("twelve") )	 return 12 ;
		if( value.startsWith("thirteen") )	 return 13 ;
		if( value.startsWith("fourrteen") )	 return 14 ;
		if( value.startsWith("fifteen") )	 return 15 ;
		if( value.startsWith("sixteen") )	 return 16 ;
		if( value.startsWith("seventeen") )	 return 17 ;
		if( value.startsWith("eightteen") )	 return 18 ;
		if( value.startsWith("nineteen") )	 return 19 ;
		if( value.startsWith("twenty") )	 return 20 ;		
		
		return null;
	}

	

	protected ArrayList<Block<ParsedScalar>> parseNonRangeValues(
			String str,
			int startIndex,
			int endIndex,
			int delimeterEnd,
			Map<String, Object> metaInfo,
			String comment)
	{
		
		ArrayList<Block<Double>> numBlockList = new ArrayList<Block<Double>>() ;		
		boolean[] occupiedPositions = (boolean[]) metaInfo.get(OCCUPIED_POSITIONS) ; 
		
		Block<Double> lBlock ;
		int off = startIndex ;
		while(true){
			try{
				lBlock = lookNearestNumberFromStart( str, off, endIndex ) ;
			}catch(Exception e){
				e.printStackTrace() ;
				break ;
			}
			if( lBlock == null )
				break ;
			
			off = lBlock.getEnd() ;
			if( !occupiedPositions[ lBlock.getStart() ] )
				numBlockList.add(lBlock) ;
		}
		if( numBlockList.isEmpty() )
			return null ;
		
		ArrayList<Block<ParsedScalar>> result = new ArrayList<Block<ParsedScalar>>() ;
		
		Block<ParsedScalar> rangeBlock = null ;
		
		int size_minus_one = numBlockList.size()-1;
		Block<Double> lastNumBlock = numBlockList.get( size_minus_one );
		
		String endString = str.substring( lastNumBlock.getEnd(), endIndex ).trim() ;
		if( endString.length() == 0 && endIndex < str.length() ){
			lBlock = lookNearestNumberFromStart( str, delimeterEnd, str.length() ) ;
			if ( lBlock != null ){
				ParsedScalar rangeScalar = new ParsedScalar( lastNumBlock.getVal(), lBlock.getVal(), comment) ;
				rangeBlock = new Block<ParsedScalar>(str, lastNumBlock.getStart(), lBlock.getEnd(), rangeScalar, Block.BLOCK_KIND_SCALAR ) ;
			}
		}		
		
		for( Block<Double> numBlock : numBlockList ){			 
			ParsedScalar ps = new ParsedScalar( numBlock.getVal(), comment) ;
			Block<ParsedScalar> blk = new Block<ParsedScalar>( str, numBlock.getStart(), numBlock.getEnd(), ps, Block.BLOCK_KIND_SCALAR ) ;
			result.add( blk ) ;
		}
		
		if( rangeBlock != null )
			result.set(size_minus_one, rangeBlock ) ;
		
		return !result.isEmpty() ? result : null ;
	}
	
	protected void calculateMask( String s, Map<String, Object> metaInfo) {
//		boolean[] bArr = calculateOccupied( s ) ;
//		metaInfo.put(OCCUPIED_POSITIONS, bArr) ;
	}

	
//	private static boolean[] calculateOccupied( String str )
//	{
//		DateParser dateParser = new DateParser() ;
//		DimensionParser dimensionParser = new DimensionParser() ; //(DimensionParser) DefaultParserProvider.getInstance().getParser( ParsedDimension.ID) ;
//		
//		ArrayList<Block<ParsedDimension>> dimensionsBlockList = new ArrayList<Block<ParsedDimension>>() ;		
//		dimensionParser.indicateTargetValues( str, dimensionsBlockList, new HashMap<String, Object>(), null ) ;
//		
//		ArrayList<Block<ParsedDate>> dateBlockList = new ArrayList<Block<ParsedDate>>() ;		
//		dateParser.indicateTargetValues( str, dateBlockList, null, null ) ;
//		
//		boolean[] result = new boolean[str.length()] ;
//		for( int i = 0 ; i < result.length ; i++ )
//			result[i] = false ;
//		
//		for( Block<?> blk : dimensionsBlockList ) {
//			int start = blk.getStart();
//			int end = blk.getEnd();
//			for( int i = start ; i < end ; i++ )
//				result[i] = true ;
//		}
//		
//		for( Block<?> blk : dateBlockList ) {
//			int start = blk.getStart();
//			int end = blk.getEnd();
//			for( int i = start ; i < end ; i++ )
//				result[i] = true ;
//		}		
//		return result;
//	}




	protected Block<ParsedScalar> parseRangeValue(
			String str, int[] bounds,Map<String, Object> metaInfo,
			String comment) {
		
		return null;
	}

	protected void performSpecialProcessing(
			String _str,
			ArrayList<Block<ParsedScalar>> blockList,
			Map<String, Object> metaInfo, String comment) {
		
		if( blockList != null && blockList.size() != 0 )
			return ;
		
		String str = _str.trim() ;
		
		int ind = str.indexOf(' ') ;
		ind = ind < 0 ? str.length() : ind ;
		str = str.substring(0, ind) ;
		
		Integer iVal = readNumber(str) ;
		if( iVal == null )
			return ;
		
		ParsedScalar ps = new ParsedScalar( iVal.doubleValue(), comment ) ;
		Block<ParsedScalar> blk = new Block<ParsedScalar>(str, 0, ind, ps, Block.BLOCK_KIND_SCALAR) ;
		blockList.add(blk) ;		
	}


	protected boolean areAlternatives(ParsedScalar val0, ParsedScalar val1) {
		return false;
	}


	protected ParsedScalar mergeValue(ParsedScalar val0, ParsedScalar val1) {
		return null;
	}
	

}
